package com.pason.onlineshop.mainshop.service.entity.query.impl;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.pason.onlineshop.mainshop.application.ShopConfiguration;
import com.pason.onlineshop.mainshop.service.entity.query.IQueryDataEntityService;
import com.pason.onlineshop.mainshop.service.entity.query.impl.QueryParameter.QueryOperateType;

@Service("queryDataEntityService")
public class QueryDataEntityServiceImpl implements IQueryDataEntityService{
	private Log log = LogFactory.getLog(IQueryDataEntityService.class);	
	private String errorCode;
	
	@PersistenceContext
	private EntityManager em;
	
	@Autowired(required=true) 
	private ShopConfiguration shopConfiguration;

    public QueryDataEntityServiceImpl() {
    }

    public QueryDataEntityServiceImpl(String errorCode) {
        this.errorCode = errorCode;
    }

    @SuppressWarnings("unchecked")
    public <T> List<T> queryByPropertys(QueryCondition queryCondition) {
    	String querySymbols = shopConfiguration.getJpaQuerySymbols();
        StringBuffer sqlBuffer = new StringBuffer();
        sqlBuffer.append(" select model \n");
        sqlBuffer.append(" from " + queryCondition.getModelName() + " as model \n");
        boolean first = true;
        for (int pi = 0; pi < queryCondition.getParameters().size(); pi++) {
            if (queryCondition.getParameters().get(pi).getParameterName() != null) {
                if (first) {
                    sqlBuffer.append(" where ");
                    first = false;
                } else {
                    sqlBuffer.append(" and ");
                }
                if (queryCondition.getParameters().get(pi).getParameterType() == QueryOperateType.Equal) {
                    sqlBuffer.append(" (");
                    if(queryCondition.getParameters().get(pi).isPrameterValueIsList()) {
                    	List<String> values = (List<String>)queryCondition.getParameters().get(pi).getParameterValue();
                    	for(int i=0; i< values.size(); i++) {
                    		sqlBuffer.append("model."
                                    + queryCondition.getParameters().get(pi).getParameterName()
                                    + " = "
                                    + querySymbols
                                    + queryCondition.getParameters().get(pi).getParameterName()+i);
                    		if(i < values.size() - 1){
                    			sqlBuffer.append(" or ");
                    		}
                    	}
                    } else {
                    	sqlBuffer.append("model."
                                + queryCondition.getParameters().get(pi).getParameterName()
                                + " = "
                                + querySymbols
                                + queryCondition.getParameters().get(pi).getParameterName());
                    }
                    sqlBuffer.append(") \n");
                } else if (queryCondition.getParameters().get(pi).getParameterType() == QueryOperateType.CharIn) {
                    sqlBuffer.append(" (");
                    if(queryCondition.getParameters().get(pi).isPrameterValueIsList()) {
                    	List<String> values = (List<String>)queryCondition.getParameters().get(pi).getParameterValue();
                    	for(int i = 0; i < values.size(); i++) {
                    		sqlBuffer.append("InStr(model."
                                    + queryCondition.getParameters().get(pi).getParameterName()
                                    + " , "
                                    + querySymbols
                                    + queryCondition.getParameters().get(pi).getParameterName()+i + ") > 0");
                    		if(i < values.size() - 1){
                    			sqlBuffer.append(" or ");
                    		}
                    	}
                    } else {
                    	sqlBuffer.append("InStr(model."
                                + queryCondition.getParameters().get(pi).getParameterName()
                                + " , "
                                + querySymbols
                                + queryCondition.getParameters().get(pi).getParameterName() + ") > 0");
                    }
                    sqlBuffer.append(") \n");
                }
            }
        }
        List<T> list = new ArrayList<T>();
        try {
        	log.debug("\n~~~~~~~ SQL String ~~~~~~~~~~\n");
            log.debug(sqlBuffer.toString());
            log.debug("\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
            Query queryObject = em.createQuery(sqlBuffer
                    .toString());
            for (int li = 0; li < queryCondition.getParameters().size(); li++) {
        		QueryParameter qm = queryCondition.getParameters().get(li);
            	if(qm.isPrameterValueIsList()) {
            		List<String> values = (List<String>) qm.getParameterValue();
            		for(int i = 0; i < values.size(); i++) {
            			queryObject.setParameter(qm.getParameterName()+i, values.get(i));
            		}
            	} else {
                    queryObject.setParameter(qm.getParameterName(), qm.getParameterValue());
            	}
            }
            list = queryObject.getResultList();
            em.close();

        } catch (RuntimeException re) {
            errorCode += "CM000006";
            log.info("queryByPropertys error");
            throw re;
        }
        return list;
    }

    public void setErrorCode(String errorCode) {
        this.errorCode = errorCode;
    }

    public String getErrorCode() {
        return errorCode;
    };
}
